/****************************************************************************************
*
* Virtually all of the code in this file is from the paper "OLE DB for the
* ODBC Programmer" by Michael Pizzo and Jeff Cochran avialable at:
*
*   http://www.microsoft.com/data/oledb/prodinfo/wpapers/oledb4odbc.htm
*
* as well as within the Data Access 2.0(+) SDK
*
*****************************************************************************************

/****************************************************************************************
*
* To paraphrase a well known author:
*
* If this code works, it was written by Ken Rahmes with a lot of help from Don Willits.
* Otherwise, Don wrote it all by himself!
*
*****************************************************************************************
*/

#define UNICODE
#define _UNICODE

#include <comdef.h>
#include <string.h>
#include <stdio.h>
#include <conio.h>

#define DBINITCONSTANTS //Initialize OLE DB constants...
#define INITGUID        // ...once in each app

#include <oledb.h>      // OLE DB include files
#include <oledberr.h>
#include <msdaguid.h>   // ODBC provider include files
#include <msdasql.h>    // MSDASQL include files
#include <sqloledb.h>   // SQLOLEDB include files
#include <MSjetoledb.h> // MSJETOLEDB include files
#include <msdaora.h>    // MSDAORA include files

static void OLEDB_Connect ( CLSID   clsidProvider,         // Object Class Identifier
                            BSTR    bstrDataSource,        // DBPROP_INIT_DATASOURCE
                            BSTR    bstrUserID,            // DBPROP_AUTH_USERID
                            BSTR    bstrPassword,          // DBPROP_AUTH_PASSWORD
                            BSTR    bstrProviderString,    // DBPROP_INIT_PROVIDERSTRING
                            BSTR    bstrInitCatalog );     // DBPROP_INIT_CATALOG

/********************************************************************
* OLE DB application main()
********************************************************************/


void main( void )
{
    BSTR   bstrEmpty = NULL;


    // Initialize OLE
    CoInitialize(NULL);

    printf ( "DSN Connection to ODBC Drivers:\n\n" );

    printf ( "Access ODBC Driver...\n" );
    {
        // This code assumes that the ODBC Data Source OLE_DB_NWind_Jet
        // was created by the installation of the DATA ACCESS 2.0 SDK

        // Access ODBC Driver via DSN 
        // Using OLE DB Properties explciitly
        OLEDB_Connect( CLSID_MSDASQL,
                       SysAllocString(OLESTR("OLE_DB_NWind_Jet")),
                       SysAllocString(OLESTR("sa")),
                       SysAllocString(OLESTR("")),
                       bstrEmpty,
                       bstrEmpty);

        // The next 2 calls cheat shamelessly, just passing variations of the
        // same (effectively) ODBC Conneciton String.
        OLEDB_Connect( CLSID_MSDASQL,
                       bstrEmpty,
                       bstrEmpty,
                       bstrEmpty,
                       SysAllocString(OLESTR("PROVIDER=MSDASQL;")
                                      OLESTR("DSN=OLE_DB_NWind_Jet;")
                                      OLESTR("UID=admin;PWD=;")),
                       bstrEmpty);

        OLEDB_Connect( CLSID_MSDASQL,
                       bstrEmpty,
                       bstrEmpty,
                       bstrEmpty,
                       SysAllocString(OLESTR("DSN=OLE_DB_NWind_Jet;")
                                      OLESTR("UID=admin;PWD=;")),
                       bstrEmpty);
    }

    printf ( "Oracle ODBC Driver...\n" );
    {
        // This code assumes you have Oracle Client software installed,
        // that you have an oracle Server named "dseOracle8" and that
        // you have an ODBC Data Source named "dseOracleDSN" that
        // references this server.
    
        // Oracle ODBC Driver via DSN
        OLEDB_Connect( CLSID_MSDASQL,
                       SysAllocString(OLESTR("dseOracleDSN")),
                       SysAllocString(OLESTR("demo")),
                       SysAllocString(OLESTR("demo")),
                       bstrEmpty,
                       bstrEmpty);

        // The next call cheats shamelessly, just passing variations of the
        // same (effectively) ODBC Conneciton String.


        OLEDB_Connect( CLSID_MSDASQL,
                       bstrEmpty,
                       bstrEmpty,
                       bstrEmpty,
                       SysAllocString(OLESTR("DSN=dseOracleDSN;")
                                      OLESTR("UID=demo;PWD=demo;")),
                       bstrEmpty);
    }

    printf ( "SQL Server ODBC Driver...\n" );
    {
        // This code assumes you have SQL Server installed with
        // an ODBC Data Source named "LocalServer"
        OLEDB_Connect( CLSID_MSDASQL,
                       SysAllocString(OLESTR("LocalServer")),
                       SysAllocString(OLESTR("sa")),
                       SysAllocString(OLESTR("")),
                       bstrEmpty,
                       SysAllocString(OLESTR("pubs")));

        OLEDB_Connect( CLSID_MSDASQL,
                       SysAllocString(OLESTR("LocalServer")),
                       SysAllocString(OLESTR("sa")),
                       SysAllocString(OLESTR("")),
                       SysAllocString(OLESTR("database=pubs")),
                       bstrEmpty);
        
        // The next 2 calls cheat shamelessly, just passing variations of the
        // same (effectively) ODBC Conneciton String.

        // SQL Server ODBC Driver via DSN
        OLEDB_Connect( CLSID_MSDASQL,
                       bstrEmpty,
                       bstrEmpty,
                       bstrEmpty,
                       SysAllocString(OLESTR("PROVIDER=MSDASQL;")
                                      OLESTR("DSN=LocalServer;")
                                      OLESTR("database=Master;")
                                      OLESTR("UID=sa;pwd=;")),
                       bstrEmpty);
              
        OLEDB_Connect( CLSID_MSDASQL,
                       bstrEmpty,
                       bstrEmpty,
                       bstrEmpty,
                       SysAllocString(OLESTR("DSN=LocalServer;")
                                      OLESTR("database=Master;")
                                      OLESTR("UID=sa;pwd=;")),
                       bstrEmpty);
    }

    printf ( "\nDSN-Less Connection String to ODBC Drivers:\n\n" );
    // A DSN-Less connection implies that the only provider property you'll
    // set is DBPROP_PROVIDER_STRING.

    printf ( "Access ODBC Driver...\n" );
    {
        // This code assumes you have the NWIND access database
        // in a path C:\_data

        // Access ODBC Driver via DSN-Less
        OLEDB_Connect( CLSID_MSDASQL,
                       bstrEmpty,
                       bstrEmpty,
                       bstrEmpty,
                       SysAllocString(OLESTR("PROVIDER=MSDASQL;")
                                      OLESTR("DRIVER={Microsoft Access Driver (*.mdb)};")
                                      OLESTR("DBQ=C:\\_data\\NWind.mdb;")
                                      OLESTR("UID=sa;PWD=;")),
                       bstrEmpty);

        OLEDB_Connect( CLSID_MSDASQL,
                       bstrEmpty,
                       bstrEmpty,
                       bstrEmpty,
                       SysAllocString(OLESTR("DRIVER={Microsoft Access Driver (*.mdb)};")
                                      OLESTR("DBQ=C:\\_data\\NWind.mdb;")
                                      OLESTR("UID=sa;PWD=;")),
                       bstrEmpty );
    }

    printf ( "Oracle ODBC Driver...\n" );
    {
        // This code assumes you have Oracle Client software installed,
        // that you have an oracle Server named "dseOracle8"
   
        OLEDB_Connect( CLSID_MSDASQL,
                       bstrEmpty,
                       bstrEmpty,
                       bstrEmpty,
                       SysAllocString(OLESTR("DRIVER={Microsoft ODBC for Oracle};")
                                      OLESTR("SERVER=dseOracle8;")
                                      OLESTR("UID=demo;PWD=demo;")),
                       bstrEmpty);
    }

    printf ( "SQL Server ODBC Driver...\n" );
    {
        // This code assumes you have SQL Server named "zhadumnt"

        OLEDB_Connect( CLSID_MSDASQL,
                       bstrEmpty,
                       bstrEmpty,
                       bstrEmpty,
                       SysAllocString(OLESTR("PROVIDER=MSDASQL;" )
                                      OLESTR("DRIVER={SQL Server};")
                                      OLESTR("SERVER=zhadumnt;DATABASE=pubs;")
                                      OLESTR("UID=sa;PWD=;")),
                       bstrEmpty);

        OLEDB_Connect( CLSID_MSDASQL,
                       bstrEmpty,
                       bstrEmpty,
                       bstrEmpty,
                       SysAllocString(OLESTR("DRIVER={SQL Server};")
                                      OLESTR("SERVER=zhadumnt;DATABASE=pubs;")
                                      OLESTR("UID=sa;PWD=;")),
                       bstrEmpty);
    }

    printf ( "\nConnection String to Native OLE DB Providers:\n\n" );

    printf ( "Jet OLE DB Native Provider...\n" );
    {
        // This code assumes you have the NWIND access database
        // in a path C:\_data

        OLEDB_Connect( CLSID_JETOLEDB_4_00,
                       SysAllocString(OLESTR("C:\\_data\\NWind.mdb")),
                       SysAllocString(OLESTR("Admin")),
                       bstrEmpty,
                       bstrEmpty,
                       bstrEmpty);
    }

    printf ( "Oracle OLE DB Native Provider...\n" );
    {
        // This code assumes you have Oracle Client software installed,
        // that you have an oracle Server named "dseOracle8"
        OLEDB_Connect( CLSID_MSDAORA,
                       SysAllocString(OLESTR("dseOracle8")),
                       SysAllocString(OLESTR("demo")),
                       SysAllocString(OLESTR("demo")),
                       bstrEmpty,
                       bstrEmpty);
    }

    printf ( "SQL Server OLE DB Native Provider...\n" );
    {
        // This code assumes you have SQL Server named "zhadumnt"
        OLEDB_Connect( CLSID_SQLOLEDB,
                       SysAllocString(OLESTR("zhadumnt")),
                       SysAllocString(OLESTR("sa")),
                       SysAllocString(OLESTR("")),
                       bstrEmpty,
                       SysAllocString(OLESTR("pubs")));

        OLEDB_Connect( CLSID_SQLOLEDB,
                       SysAllocString(OLESTR("zhadumnt")),
                       SysAllocString(OLESTR("sa")),
                       SysAllocString(OLESTR("")),
                       SysAllocString(OLESTR("database=pubs;")),
                       bstrEmpty);
    }

    CoUninitialize();

} // End of Main



static void OLEDB_Connect ( CLSID   clsidProvider,       // Object Class Identifier
                            BSTR    bstrDataSource,      // DBPROP_INIT_DATASOURCE
                            BSTR    bstrUserID,          // DBPROP_AUTH_USERID
                            BSTR    bstrPassword,        // DBPROP_AUTH_PASSWORD
                            BSTR    bstrProviderString,  // DBPROP_INIT_PROVIDERSTRING
                            BSTR    bstrInitCatalog )    // DBPROP_INIT_CATALOG
{

  IDBProperties*  pIDBProperties = NULL;
  IDBInitialize*  pIDBInitialize = NULL;
  DBPROP          InitProperties[5]; // KISS - We'll never have more than 5 properties
  DBPROPSET       rgInitPropSet;
  HRESULT         hr;
  ULONG           i;
  ULONG           j = 0;
  ULONG           nProps;



  // Create an instance of the Provider.
  CoCreateInstance(clsidProvider, NULL, CLSCTX_INPROC_SERVER,
                   IID_IDBInitialize, (void**)&pIDBInitialize);

  if (pIDBInitialize == NULL) {
    printf( "\t CoCreateInstance COULD NOT INITIALIZE PROVIDER!!!\n");
    return;
  }


  // Level of prompting that will be done to complete the
  // connection process
  VariantInit(&InitProperties[0].vValue);
  InitProperties[0].dwPropertyID = DBPROP_INIT_PROMPT;
  InitProperties[0].vValue.vt = VT_I2;
  InitProperties[0].vValue.iVal = DBPROMPT_NOPROMPT;

  if ((wchar_t *) bstrDataSource != NULL) {
    // The Data Source/Server parameter in ADO Connection Strings is set
    // in OLE DB using the similarly named property.
    j++;
    VariantInit(&InitProperties[j].vValue);
    InitProperties[j].dwPropertyID = DBPROP_INIT_DATASOURCE;	
    InitProperties[j].vValue.vt = VT_BSTR;
    InitProperties[j].vValue.bstrVal = bstrDataSource;
  }

  if ((wchar_t *) bstrUserID != NULL) {
    // User ID
    j++;
    VariantInit(&InitProperties[j].vValue);
    InitProperties[j].dwPropertyID = DBPROP_AUTH_USERID;
    InitProperties[j].vValue.vt = VT_BSTR;
    InitProperties[j].vValue.bstrVal = bstrUserID;
  }

  if ((wchar_t *) bstrPassword != NULL) {
    // Password
    j++;
    VariantInit(&InitProperties[j].vValue);
    InitProperties[j].dwPropertyID = DBPROP_AUTH_PASSWORD;
    InitProperties[j].vValue.vt = VT_BSTR;
    InitProperties[j].vValue.bstrVal = bstrPassword;
  }

  if ((wchar_t *) bstrProviderString != NULL) {
    // The Provider String in OLE DB is roughly equivalent to the Connection String
    // in ADO.  However, whenever possible, the actual properties should be set individually.
    j++;
    VariantInit(&InitProperties[j].vValue);
    InitProperties[j].dwPropertyID = DBPROP_INIT_PROVIDERSTRING;
    InitProperties[j].vValue.vt = VT_BSTR;
    InitProperties[j].vValue.bstrVal = bstrProviderString;
  }

  if ((wchar_t *) bstrInitCatalog != NULL) {
    // The Initail Catalog in OLE DB is roughly equivalent to DATABASE= clause
    // supported by some ODBC Drivers
    j++;
    VariantInit(&InitProperties[j].vValue);
    InitProperties[j].dwPropertyID = DBPROP_INIT_CATALOG;
    InitProperties[j].vValue.vt = VT_BSTR;
    InitProperties[j].vValue.bstrVal = bstrProviderString;
  }


  nProps = ++j;

  // Initialize common property options.
  for ( i = 0; i < nProps; i++ ) {
      InitProperties[i].dwOptions = DBPROPOPTIONS_REQUIRED;
      InitProperties[i].colid = DB_NULLID;
  }

  rgInitPropSet.guidPropertySet = DBPROPSET_DBINIT;
  rgInitPropSet.cProperties = nProps;
  rgInitPropSet.rgProperties = InitProperties;

  // Set initialization properties.
  pIDBInitialize->QueryInterface(IID_IDBProperties, (void**) &pIDBProperties);
  hr = pIDBProperties->SetProperties(1, &rgInitPropSet);

  if (FAILED(hr))
    printf( "\t Set properties failed.");

  // Here is where the Data Source Object (SQLOLEDB/MSDASQL/MSDAORA - The Provider)
  // connects to the data source (SQL Server/Access/Oracle) using the properties
  // set above in the call to pIDBProperties->SetProperties().
  hr = pIDBInitialize->Initialize();

  if (FAILED(hr))
    printf( "\t FAILED TO CONNECT!!!\n");
  else
    printf( "\t SUCCESSFUL CONNECTION!!!\n" );

  // Release the IDBProperties interface
  pIDBProperties->Release();

  // Disconnect from the data source.
  if (pIDBInitialize != NULL)
    pIDBInitialize->Release();

  for ( i=1;i < nProps;i++)
    SysFreeString(InitProperties[i].vValue.bstrVal);

} // End of OLEDB_Connect


